import { initState } from './state.js'
import { compileToFunctions } from './compiler/index.js'
import { callHook, mountComponent } from './lifecycle.js'
import { mergeOptions } from './util/index.js'

/**
 * 1. 挂载 _init 方法到 vue 实例上
 */
function initMixin(Vue) {
  // 挂载 _init 方法到 vue 实例上
  Vue.prototype._init = function (options) {
    const vm = this

    // 将传入的 options 挂载到 $options 实例属性上
    // 后续可以直接通过实例取到传入的 options
    vm.$options = mergeOptions(vm.constructor.options, options)

    callHook(vm, 'beforeCreate')
    // 初始化状态
    initState(vm)
    callHook(vm, 'created')

    if (vm.$options.el) {
      vm.$mount(vm.$options.el)
    }
  }

  // 这块代码在源码里面的位置其实是放在entry-runtime-with-compiler.js里面
  // 代表的是Vue源码里面包含了compile编译功能 这个和runtime-only版本需要区分开
  Vue.prototype.$mount = function (el) {
    debugger
    const vm = this
    const options = vm.$options
    el = document.querySelector(el)

    // 如果不存在render函数
    if (!options.render) {
      let template = options.template
      if (!template && el) {
        // 如果不存在 render 和 template
        // 直接将模板赋值到 el 所在的外层 html 结构 (就是 el 本身 并不是 父元素)
        template = el.outerHTML
      }

      // 最终把 模板 编译成 render 函数
      if (template) {
        const render = compileToFunctions(template)
        options.render = render
      }
    }

    // 将当前组件实例挂载到真实的 el 节点上
    return mountComponent(vm, el)
  }
}

export { initMixin }
